/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package db.server.Connection;

import db.server.BUS.QueryBUS;
import db.server.DTO.DatabaseDTO;
import db.server.DTO.EditTableDTO;
import db.server.DTO.QueryDTO;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.ParserConfigurationException;

/**
 *
 * @author QuangKhai
 */
public class DBServerTrans implements Runnable{
    private ObjectOutputStream oos;        
    private ObjectInputStream ois;
    private Socket socket;
    private String username;
    private String password;
    private QueryDTO queryDTO = new QueryDTO();
    private EditTableDTO editTableDTO = new EditTableDTO();
    private QueryBUS queryBUS = new QueryBUS();
    private List<DatabaseDTO> database = new ArrayList<DatabaseDTO>();
        
    public DBServerTrans(Socket socket, String username, String password, List<DatabaseDTO> database) throws IOException{        
        this.socket = socket;
        this.username = username;
        this.password = password;  
        this.database = database;
    }
    
    public void setConnection() throws IOException{
        this.oos = new ObjectOutputStream(socket.getOutputStream()); 
        this.ois = new ObjectInputStream(socket.getInputStream());
        oos.flush();        
    }
    
    public List<String> recieveClient() throws IOException{
        List<String> client = new ArrayList<String>();
        
        client.add(ois.readUTF());
        client.add(ois.readUTF());
        
        return client;
    }
    
    public void sendState(boolean state) throws IOException{
        if(state){
            oos.writeUTF("Kết nối thành công");
            oos.flush();            
        }else{
            oos.writeUTF("Đăng nhập không hợp lệ");
            oos.flush();            
        }
    }
    
    public int recieveType() throws IOException{ 
        String s = ois.readUTF();
        if(s.compareTo("Client") == 0){
            return 1;
        } else if(s.compareTo("Execute") == 0){
            return 2;
        }               
        return 0;
    }
    
    public void sendResult() throws IOException, ParserConfigurationException{
        String type = queryDTO.getQuerySentences().get(0).split(" ")[0];
        DatabaseDTO databaseDTO = new DatabaseDTO();
        
        for(int i = 0; i < database.size(); i++){
            if(database.get(i).getDatabaseName().compareTo(queryDTO.getDatabaseName()) == 0){
                databaseDTO = database.get(i);
                break;
            }
        }
        
        if(type.compareTo("SELECT") == 0){
            editTableDTO = queryBUS.getSelectResults(queryDTO.getQuerySentences().get(0), databaseDTO);
            sendEditTable(editTableDTO);
        }else if(type.compareTo("INSERT") == 0){
            editTableDTO = queryBUS.getInsertResults(queryDTO.getQuerySentences().get(0), databaseDTO);
            sendEditTable(editTableDTO);
        } else if(type.compareTo("DELETE") == 0){
            editTableDTO = queryBUS.getDeleteResults(queryDTO.getQuerySentences().get(0), databaseDTO);
            sendEditTable(editTableDTO);
        } else if(type.compareTo("UPDATE") == 0){
            editTableDTO = queryBUS.getUpdateResults(queryDTO.getQuerySentences().get(0), databaseDTO);
            sendEditTable(editTableDTO);
            
        }    
    }  
    
    public void sendEditTable(EditTableDTO editTable) throws IOException{
        int colums = editTable.getColumnName().size();
        oos.writeInt(colums);
        oos.reset();
        
        for(int i = 0; i < colums; i++){
            oos.writeUTF(editTable.getColumnName().get(i));
            oos.reset();
        }
        
        int values = editTable.getLstValues().size();
        oos.writeInt(values);
        oos.reset();
        for(int i = 0; i < values; i++){
            for(int j = 0; j < colums; j++){
                oos.writeUTF(editTable.getLstValues().get(i).get(j));
                oos.reset();
            }
        }
    }
    
    public void sendDatabase() throws IOException{
        oos.writeInt(database.size());
        oos.reset();
        
        for(int i = 0; i < database.size(); i++){            
            oos.writeUTF(database.get(i).getDatabaseName());
            oos.reset();       
            
            oos.writeInt(database.get(i).getLstTableDTO().size());
            oos.reset();       
            for(int j = 0; j < database.get(i).getLstTableDTO().size(); j++){
                oos.writeUTF(database.get(i).getLstTableDTO().get(j).getTableName());
                oos.reset();  
                
                oos.writeInt(database.get(i).getLstTableDTO().get(j).getLstRows().size());
                oos.reset();       
                for(int k = 0; k < database.get(i).getLstTableDTO().get(j).getLstRows().size(); k++){
                    oos.writeUTF(database.get(i).getLstTableDTO().get(j).getLstRows().get(k).getColumnName());
                    oos.reset();  
                }
            }
        }
    }
    
    public QueryDTO receiveQuery() throws IOException, ClassNotFoundException{        
        QueryDTO query = new QueryDTO();
        List<String> lstQuerySentences = new ArrayList<String>();
        
        query.setDatabaseName(ois.readUTF());
        
        lstQuerySentences.add(ois.readUTF());
        query.setQuerySentences(lstQuerySentences);
        
        return query;
    }
    
    public void processClient() throws IOException{
        List<String> client = recieveClient();
        
        if(client.get(0).compareTo(username) == 0 && client.get(1).compareTo(password) == 0){
            sendState(true);
            sendDatabase();
        }else{
            sendState(false);
        }
    }
    
    public void processQuery() throws IOException, ClassNotFoundException, ParserConfigurationException{
        queryDTO = receiveQuery();
        sendResult();
    }
    
    @Override
    public void run() {  
        try {
            setConnection();
        } catch (IOException ex) {
            Logger.getLogger(DBServerTrans.class.getName()).log(Level.SEVERE, null, ex);
        }
        while(true){
            try {
                switch(recieveType()){
                    case 0:                        
                        break;
                    case 1:
                        processClient();
                        break;
                    case 2:
                        processQuery();
                        break;
                }
            } catch (IOException ex) {
                Logger.getLogger(DBServerTrans.class.getName()).log(Level.SEVERE, null, ex);
            }catch (ClassNotFoundException ex) {
                Logger.getLogger(DBServerTrans.class.getName()).log(Level.SEVERE, null, ex);
            } catch (ParserConfigurationException ex) {
                Logger.getLogger(DBServerTrans.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}
